🚀 解决调用 B 站 API 返回 -352 校验失败的问题

头像
2025年11月20日

在编写爬虫或第三方应用调用 Bilibili 接口(如获取热门视频列表)时,经常会遇到接口返回错误码 -352。

# 哔哩哔哩
🚀 解决调用 B 站 API 返回 -352 校验失败的问题

在编写爬虫或第三方应用调用 Bilibili 接口(如获取热门视频列表)时,经常会遇到接口返回错误码 -352

1. 问题现象

  • 目标接口https://api.bilibili.com/x/web-interface/ranking/v2 (热门排行榜)
  • 错误响应
  • 原因分析-352 是 B 站的风控(校验)拦截代码。通常是因为请求头中缺失了能够标识设备指纹的关键 Cookie(如 buvid3),服务器判定该请求为非法脚本或“裸奔”请求。

2. 解决方案:注入设备指纹 (buvid3)

要通过校验,我们需要先从 B 站的前端指纹接口获取合法的 buvid3,并将其添加到请求的 Cookie 中。

第一步:获取 buvid3

调用 B 站的前端 SPI 接口获取设备指纹。

  • 接口地址https://api.bilibili.com/x/frontend/finger/spi
  • 请求方式GET
  • 响应示例

第二步:构造请求头

拿到 b_3 的值后,需要按照特定格式拼接到 Cookie 中。

⚠️ 注意: 仅仅有 Cookie 是不够的,B 站接口通常还强校验 User-Agent,请务必带上标准的浏览器 UA。

Header 配置规范:

headers: {
    // 关键点1:Cookie 格式必须包含 "infoc" 后缀
    "Cookie": `buvid3=${b_3}infoc;`, 
  
    // 关键点2:必须伪装成浏览器,否则极易触发 -404 或 -412
    "User-Agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36",
  
    "Accept": "*/*",
    "Host": "api.bilibili.com",
    "Connection": "keep-alive"
}

3. 代码实现示例 (JavaScript/Node.js)

以下是一个完整的封装示例,自动获取指纹并请求目标接口:

const axios = require('axios');

async function fetchBilibiliRanking() {
    // 1. 获取设备指纹 buvid3
    let buvid3 = '';
    try {
        const spiResponse = await axios.get('https://api.bilibili.com/x/frontend/finger/spi');
        buvid3 = spiResponse.data.data.b_3;
        console.log('获取指纹成功:', buvid3);
    } catch (e) {
        console.error('获取指纹失败', e);
        return;
    }

    // 2. 携带 Cookie 请求目标接口
    const targetUrl = 'https://api.bilibili.com/x/web-interface/ranking/v2';
  
    try {
        const result = await axios.get(targetUrl, {
            headers: {
                // 拼接 Cookie,注意末尾的分号和 infoc 后缀
                "Cookie": `buvid3=${buvid3}infoc;`,
                "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36",
                "Referer": "https://www.bilibili.com/" // 部分接口可能检查 Referer
            }
        });

        if (result.data.code === 0) {
            console.log('数据获取成功:', result.data.data.list.slice(0, 3)); // 打印前3条
        } else {
            console.error('接口报错:', result.data);
        }
    } catch (e) {
        console.error('请求异常:', e.message);
    }
}

fetchBilibiliRanking();

💡 补充说明

  • 时效性buvid3 理论上是长效的,但在高并发场景下,建议定期重新获取或维护一个 Cookie 池。
  • 其他风控:如果加上了 buvid3 仍然报错(如 -412),可能需要进一步补充 buvid4 或检查 IP 质量。